package com.api.controller;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.IdUtil;
import com.api.config.CachService;
import com.api.config.RedisConstant;
import com.api.config.RedisService;
import com.api.domain.LoginUser;
import com.api.domain.UserDTO;
import com.api.entity.User;
import com.api.log.Log;
import com.api.utils.Result;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;

import static com.api.entity.table.UserTableDef.USER;

import java.util.HashMap;
import java.util.Map;

/**
 * @Description: 描述
 * @Author: yangshfieng
 * @CreateDate: 2023/6/14
 */
@Slf4j
@RestController
public class LoginController {

    @Autowired
    CachService cachService;
    @Autowired
    RedisService redisService;
    @Autowired
    private WxMaService wxMaService;

    /**
     * 登录
     * 接口：/doLogin
     * @return
     */
    @Log("用户登录")
    @RequestMapping("/doLogin")
    public Result doLogin(@Valid @RequestBody LoginUser loginUser) throws Exception {
        log.info("loginUser", loginUser);
        //1000.账号密码登录 1001.短信注册登录 1002.短信登录
        if(loginUser.getLoginType().intValue() == 1000){
            User user = User.create()
                    .select(USER.ALL_COLUMNS)
                    .where(USER.LOGIN_NAME.eq(loginUser.getUsername()))
                    .and(USER.STATUS.gt(0))
                    .one();
            if(null == user){
                return Result.err("账号或密码不正确");
            }
            // 校验密码
            String salt = user.getSalt();
            String pwd = SaSecureUtil.md5BySalt(loginUser.getPassword().trim(),salt.trim());
            log.info("用户输入密码： "+loginUser.getPassword().trim());
            log.info("会员的盐值： "+salt.trim());
            log.info("根据用户密码获取到的加密后的密码： "+pwd.trim());
            log.info("数据库的密码： " + user.getPassword().trim());
            if(!pwd.trim().equalsIgnoreCase(user.getPassword().trim())){
                return Result.err("账号或密码不对");
            }

            int i = 0;
            if(null == user.getStatus() || user.getStatus() != 1){
                return Result.err("当前账户异常, 不允许登录");
            }
            StpUtil.login(user.getId());
            SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
            //更新密码和盐值
            boolean b = User.create()
                    .setId(user.getId())
                    .setToken(tokenInfo.getTokenValue())
                    .updateById();
            if(b){
                Map<String,Object> res = new HashMap<>();
                UserDTO userInfo = cachService.setCachUser(user);
                return Result.ok(userInfo);
            }
            return Result.err();
        }
        else if(loginUser.getLoginType().intValue() == 1001){
            //1001.用户注册
            if(StringUtils.isEmpty(loginUser.getCode())){
                return Result.err("验证码不能为空");
            }
            if(StringUtils.isEmpty(loginUser.getPassword())){
                return Result.err("密码不能为空");
            }
            String userTele = loginUser.getUsername();
            String key = RedisConstant.USER_TELE_CODE_REGISTER + userTele;
            if(!redisService.hasKey(key)){
                return Result.err("验证码错误或过期，请重新获取");
            }
            Object tempCode = redisService.getCacheObject(key);
            if(null == tempCode){
                return Result.err("验证码错误或过期，请重新获取");
            }
            if(!tempCode.toString().equals(loginUser.getCode())){
                return Result.err("验证码错误");
            }
            User user = User.create().select(USER.ALL_COLUMNS).where(User::getUserTele).eq(userTele).and(User::getStatus).gt(0).one();
            if(null != user){
                return Result.err("当前手机号已注册，请直接登录");
            }
            //注册用户
            String salt = IdUtil.simpleUUID().substring(0,10);
            String pwd = SaSecureUtil.md5BySalt(loginUser.getPassword().trim(),salt.trim());
            boolean save = User.create()
                    .setUserTele(userTele)
                    .setLoginName(loginUser.getUsername())
                    .setNickName("新用户" + userTele.substring(loginUser.getUsername().length() - 4))
                    .setStatus(1)
                    .setSalt(salt).setPassword(pwd)
                    .save();

            if(save){
                user = User.create().select(USER.ALL_COLUMNS).where(User::getUserTele).eq(userTele).and(User::getStatus).gt(0).one();
                if(null != user){
                    StpUtil.login(user.getId());
                    SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
                    //更新密码和盐值
                    boolean b = User.create()
                            .setId(user.getId())
                            .setToken(tokenInfo.getTokenValue())
                            .updateById();
                    int i = b?1:0;
                    if(i > 0){
                        Map<String,Object> res = new HashMap<>();
                        UserDTO userInfo = cachService.setCachUser(user);
                        return Result.ok(userInfo);
                    }
                }
            }
            return Result.err();
        }
        else if(loginUser.getLoginType().intValue() == 1002){
            //1002.短信登录
            if(StringUtils.isEmpty(loginUser.getCode())){
                return Result.err("验证码不能为空");
            }
            String userTele = loginUser.getUsername();
            String key = RedisConstant.USER_TELE_CODE_LOGIN + userTele;
            if(!redisService.hasKey(key)){
                return Result.err("验证码错误或过期，请重新获取");
            }
            Object tempCode = redisService.getCacheObject(key);
            if(null == tempCode){
                return Result.err("验证码错误或过期，请重新获取");
            }
            if(!tempCode.toString().equals(loginUser.getCode())){
                return Result.err("验证码错误");
            }
            User user = User.create().select(USER.ALL_COLUMNS).where(User::getUserTele).eq(userTele).and(User::getStatus).gt(0).one();
            if(null == user){
                return Result.err("当前手机号未注册，请先注册");
            }
            if(null != user.getStatus() && user.getStatus() != 1){
                return Result.err("当前账户状态异常，不允许操作");
            }
            StpUtil.login(user.getId());
            SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
            //更新密码和盐值
            boolean b = User.create()
                    .setId(user.getId())
                    .setToken(tokenInfo.getTokenValue())
                    .updateById();
            int i = b?1:0;
            if(i > 0){
                Map<String,Object> res = new HashMap<>();
                UserDTO userInfo = cachService.setCachUser(user);
                return Result.ok(userInfo);
            }
            return Result.err();
        }
        else{
            return Result.err("非法操作");
        }
    }


    /**
     * 微信登录
     * @param code
     * @return
     */
    @Log("微信登录")
    @RequestMapping("/wxLogin")
    public Result wxLogin(String code){
        //获取openId、unionid、session_key
        WxMaJscode2SessionResult info = null;
        try {
            info = wxMaService.getUserService().getSessionInfo(code);
        } catch (WxErrorException e) {
            throw new RuntimeException(e);
        }

        log.info("info  ==>  {}",info);

        if(null == info || null == info.getSessionKey() || null == info.getOpenid()){
            return Result.err("微信登录初始化失败");
        }
        String sessionKey = info.getSessionKey();
        String openid = info.getOpenid();
        String unionid = info.getUnionid();
        boolean isNew = false;
        User user = User.create().where(User::getWxOpenId).eq(openid).and(User::getStatus).gt(0).one();
        if(null == user){
            //注册新用户
            boolean flag = User.create()
                    .setStatus(1)
                    .setWxOpenId(openid)
                    .setWxUnionId(unionid)
                    .save();
            if(!flag){
                return Result.err("注册失败");
            }
            user = User.create().where(User::getWxOpenId).eq(openid).and(User::getStatus).gt(0).one();
        }
        if(null == user.getStatus() || user.getStatus() == 2){
            return Result.err("当前用户已被锁定，无法登录");
        }
        StpUtil.login(user.getId());
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        //更新密码和盐值
        boolean b = User.create()
                .setId(user.getId())
                .setToken(tokenInfo.getTokenValue())
                .updateById();
        int i = b?1:0;
        if(i > 0){
            Map<String,Object> res = new HashMap<>();
            UserDTO userInfo = cachService.setCachUser(user);
            return Result.ok(userInfo);
        }
        return Result.err();
    }

    /**
     * 查询登录状态
     * 接口：/isLogin
     */
    @RequestMapping("/isLogin")
    public Result isLogin() {
        return Result.ok("是否登录：" + StpUtil.isLogin());
    }


    /**
     * 测试注销
     * 接口：/logout
     * @return
     */
    @Log("退出登录")
    @RequestMapping("/logout")
    public Result logout() {
        StpUtil.logout();
        return Result.ok();
    }
}
